# 公共函数
from flask import Flask,request,json,jsonify,render_template,redirect,url_for
import hashlib
import time
import base64
import hmac
from api import config_sqlite3

KEY = "JD98Dskw=23njQndW9D" # token key 密钥

def md5(s:str): # 密码MD5加密
    s = s.encode('utf-8')
    s = hashlib.md5(s).hexdigest()
    return s

def generate_token(key, expire=3600): # 生成token
    r'''
    @Args:
    key: str (用户给定的key，需要用户保存以便之后验证token,每次产生token时的key 都可以是同一个key)
    expire: int(最大有效时间，单位为s)
    @Return:
    state: str
    '''
    ts_str = str(time.time() + expire)
    ts_byte = ts_str.encode("utf-8")
    sha1_tshexstr = hmac.new(key.encode("utf-8"),ts_byte,'sha1').hexdigest() 
    token = ts_str+':'+sha1_tshexstr
    b64_token = base64.urlsafe_b64encode(token.encode("utf-8"))
    return b64_token.decode("utf-8")

def certify_token(key, token): # 验证token
    r'''
        @Args:
        key: str
        token: str
        @Returns:
        boolean
    '''
    # 解码token
    token_str = base64.urlsafe_b64decode(token).decode("utf-8")
    # 拆分token
    token_list = token_str.split(':')
    if len(token_list) != 2:
        return False
    ts_str = token_list[0]
    if float(ts_str) < time.time(): # token过期
        return False
    # 校验token
    new_token = generate_token(key, float(ts_str)-time.time())
    if new_token == token:
        return True
    return False


# 用户登录查询
def login(username:str,password:str):
    """
    用户登录,加密密码,返回token
    @param username: 用户名
    @param password: 密码
    @return:boolean,dict
    """
    # 密码MD5加密
    password = md5(password)
    # 获取数据库连接
    db = config_sqlite3.Sqlite3()
    # 查询数据库
    sql = f"select * from user where username='{username}' and password='{password}'"
    row = db.sql_select_one(sql)
    is_logiin = False
    if row: # 登录成功 生成token并返回
        id = row[0]
        key = f"{username}{KEY}{password}" # 加密key
        token = generate_token(key) # 生成token 失效时间为3600s
        update_time = int(time.time())
        # 更新数据库中的token,更新时间
        sql = f"update user set token='{token}',update_time='{update_time}' where id={id}"
        db.sql_change_msg(sql)
        is_logiin = True
        
    db.release()
    if is_logiin:
        return is_logiin,jsonify({'code':200,'msg':'登录成功','token':token,"uid":id,'username':username})
    else:
        return is_logiin,jsonify({'code':400,'msg':'用户名或密码错误'})

# 验证用户访问合法性
def certify_user(uid:int,token:str):
    # 查询用户数据
    db = config_sqlite3.Sqlite3()
    sql = f"select * from user where id={uid} and token='{token}'"
    row = db.sql_select_one(sql)
    is_login = False
    if row: # 验证成功
        is_login = certify_token(f"{row[1]}{KEY}{row[2]}",token) # 验证token是否过期
    db.release()
    return is_login

    

